package com.studyroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.studyroom.entity.Reservation;
import com.studyroom.entity.User;
import com.studyroom.entity.StudyRoom;
import com.studyroom.entity.Seat;
import com.studyroom.mapper.ReservationMapper;
import com.studyroom.service.*;
import com.studyroom.dto.SearchDTO;
import com.studyroom.exception.ServiceException;
import com.studyroom.vo.ReservationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements ReservationService {

    private static final Logger log = LoggerFactory.getLogger(ReservationServiceImpl.class);

    @Autowired
    private UserService userService;
    
    @Autowired
    private StudyRoomService studyRoomService;
    
    @Autowired
    private SeatService seatService;

    @Override
    public IPage<Reservation> search(SearchDTO params) {
        Page<Reservation> page = new Page<>(params.getCurrent(), params.getSize());
        
        // 手动处理日期时间参数
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        
        try {
            if (params.getStartTime() != null && !params.getStartTime().isEmpty()) {
                startDateTime = LocalDateTime.parse(params.getStartTime(), 
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            
            if (params.getEndTime() != null && !params.getEndTime().isEmpty()) {
                endDateTime = LocalDateTime.parse(params.getEndTime(), 
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
        } catch (Exception e) {
            throw new ServiceException("日期时间格式不正确: " + e.getMessage());
        }
        
        // 传递转换后的日期时间参数
        return baseMapper.searchReservations(page, params.getRoomId(), startDateTime, endDateTime);
    }

    @Override
    public boolean endReservation(Long id) {
        Reservation reservation = getById(id);
        if (reservation != null) {
            reservation.setStatus(0); // 设置状态为已取消
            return updateById(reservation);
        }
        return false;
    }

    @Override
    public Page<Reservation> getMyReservations(String username, Integer status, Page<Reservation> page) {
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 使用自定义SQL查询，以便关联自习室和座位表获取名称
        Page<Reservation> result = baseMapper.getMyReservations(page, user.getId(), status);
        
        // 打印第一条数据的详细信息
        if (result.getRecords() != null && !result.getRecords().isEmpty()) {
            Reservation firstRecord = result.getRecords().get(0);
            System.out.println("\n=== Reservation Data Flow Tracking ===");
            System.out.println("1. Raw Data from Database:");
            System.out.println("ID: " + firstRecord.getId());
            System.out.println("StartTime Type: " + firstRecord.getStartTime().getClass().getName());
            System.out.println("StartTime Value: " + firstRecord.getStartTime());
            System.out.println("EndTime Type: " + firstRecord.getEndTime().getClass().getName());
            System.out.println("EndTime Value: " + firstRecord.getEndTime());
            System.out.println("CreatedAt Type: " + firstRecord.getCreatedAt().getClass().getName());
            System.out.println("CreatedAt Value: " + firstRecord.getCreatedAt());
            System.out.println("Complete Record: " + firstRecord);
            System.out.println("=====================================\n");
        }

        return result;
    }

    @Override
    @Transactional
    public Reservation createReservation(String username, Reservation reservation) {
        // 1. 获取用户信息
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 2. 检查自习室和座位是否可用
        StudyRoom room = studyRoomService.getById(reservation.getRoomId());
        if (room == null || room.getStatus() != 1) {
            throw new ServiceException("自习室不可用");
        }

        Seat seat = seatService.getById(reservation.getSeatId());
        if (seat == null || seat.getStatus() != 1 || seat.getIsOccupied() == 1) {
            throw new ServiceException("座位不可用");
        }

        // 3. 检查时间冲突
        checkTimeConflict(reservation.getSeatId(), reservation.getStartTime(), reservation.getEndTime());

        // 4. 创建预约
        reservation.setUserId(user.getId());
        reservation.setStatus(1); // 设置为待使用
        reservation.setCreatedAt(LocalDateTime.now());
        
        save(reservation);
        
        return reservation;
    }

    @Override
    @Transactional
    public void cancelReservation(String username, Long id) {
        // 1. 获取用户信息
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 2. 获取预约信息
        Reservation reservation = getById(id);
        if (reservation == null) {
            throw new ServiceException("预约不存在");
        }

        // 3. 验证是否是当前用户的预约
        if (!reservation.getUserId().equals(user.getId())) {
            throw new ServiceException("无权操作此预约");
        }

        // 4. 检查预约状态是否可取消
        if (reservation.getStatus() != 1) {
            throw new ServiceException("当前状态不可取消");
        }

        // 5. 取消预约
        reservation.setStatus(0); // 设置状态为已取消
        updateById(reservation);
    }

    @Override
    @Transactional
    public boolean deleteReservation(Long id) {
        // 获取预约信息
        Reservation reservation = this.getById(id);
        if (reservation == null) {
            throw new RuntimeException("预约不存在");
        }
        
        // 如果预约状态为生效中或使用中，需要更新座位状态
        if (reservation.getStatus() == 1 || reservation.getStatus() == 2) {
            // 更新座位状态为可用
            seatService.updateSeatOccupation(reservation.getSeatId(), false);
        }
        
        // 删除预约记录
        return this.removeById(id);
    }

    private void checkTimeConflict(Long seatId, LocalDateTime startTime, LocalDateTime endTime) {
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getSeatId, seatId)
               .eq(Reservation::getStatus, 1)
               .and(w -> w.between(Reservation::getStartTime, startTime, endTime)
                        .or()
                        .between(Reservation::getEndTime, startTime, endTime));

        if (count(wrapper) > 0) {
            throw new ServiceException("所选时间段已被预约");
        }
    }

    @Override
    public List<ReservationVO> getUserConflictReservations(Long userId, LocalDateTime startTime,
                                                           LocalDateTime endTime, List<Integer> statusList) {
        
        log.info("检查用户预约冲突 - userId: {}, startTime: {}, endTime: {}, statusList: {}", 
            userId, startTime, endTime, statusList);
        
        // 查询用户在指定时间段内的预约
        List<Reservation> conflictReservations = this.baseMapper.selectList(
            new LambdaQueryWrapper<Reservation>()
                .eq(Reservation::getUserId, userId)
                .in(Reservation::getStatus, statusList)
                .and(w -> w
                    .between(Reservation::getStartTime, startTime, endTime)
                    .or()
                    .between(Reservation::getEndTime, startTime, endTime)
                    .or()
                    .and(v -> v
                        .le(Reservation::getStartTime, startTime)
                        .ge(Reservation::getEndTime, endTime)
                    )
                )
        );
        
        log.info("检查结果 - 找到冲突预约数量: {}", conflictReservations.size());
        
        // 转换为VO并返回
        return conflictReservations.stream().map(r -> {
            ReservationVO vo = new ReservationVO();
            BeanUtils.copyProperties(r, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public Integer getUserCancelledCountLastWeek(String username) {
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        
        // 获取一周前的时间
        LocalDateTime oneWeekAgo = LocalDateTime.now().minusDays(7);
        
        // 查询一周内取消的预约
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getUserId, user.getId())
               .eq(Reservation::getStatus, 0)  // 状态为0表示已取消
               .ge(Reservation::getCreatedAt, oneWeekAgo);  // 使用createdAt替代updatedAt
        
        return Math.toIntExact(this.count(wrapper));  // 转换long为Integer
    }
} 